package club.web51.classroom_tool.Config;

import club.web51.classroom_tool.Enums.MsgEnum;
import club.web51.classroom_tool.Exceptions.ErrDataException;
import club.web51.classroom_tool.Utils.MsgUtil;
import club.web51.classroom_tool.Utils.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Classname AuthFilter
 * @Description TODO
 * @Date 2020/11/17  14:46
 * @Created by wxt
 */
@Component
public class AuthFilter extends AuthenticatingFilter {

    /**
     * 从请求头读取Token
     * @param servletRequest
     * @param servletResponse
     * @return
     * @throws Exception
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //获取请求token
        String token = request.getHeader("Authentication");
        return new UserAuthToken(token);
    }


    /**
     * 步骤1.所有请求全部拒绝访问
     *
     * @param request
     * @param response
     * @param mappedValue
     * @return
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        if (((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())) {
            return true;
        }
        return false;

    }
        /**
         *  权限拒绝处理
         * @param servletRequest
         * @param servletResponse
         * @return
         * @throws Exception
         */
    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        Boolean r = executeLogin(servletRequest,servletResponse);
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String token = request.getHeader("Authentication");
        if(ObjectUtil.isNull(token) || "".equals(token)){
            HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
            httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpResponse.setHeader("Access-Control-Allow-Origin", "*");
            httpResponse.setCharacterEncoding("UTF-8");
            ObjectMapper mapper = new ObjectMapper();
            String res = null;
            try {
                res = mapper.writeValueAsString(MsgUtil.get(MsgEnum.ERROR_NO_ROOT));
            } catch (JsonProcessingException jsonProcessingException) {
                jsonProcessingException.printStackTrace();
            }
            try {
                httpResponse.getWriter().print(res);
                httpResponse.getWriter().close();
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }

        return r;
    }


    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setCharacterEncoding("UTF-8");
        ObjectMapper mapper = new ObjectMapper();
        String res = null;
        try {
            res = mapper.writeValueAsString(MsgUtil.get(MsgEnum.ERROR_USER_LOGIN_EXIST));
        } catch (JsonProcessingException jsonProcessingException) {
            jsonProcessingException.printStackTrace();
        }
        try {

            httpResponse.getWriter().print(res);
            httpResponse.getWriter().close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        return false;

    }
}

